package com.gk.test.prototype;

import lombok.Data;
import lombok.SneakyThrows;

import java.io.*;
import java.util.Date;

/**
 * 原型模式
 * 因为原有的原型模式实现深克隆很麻烦，因此我们可以直接让类进行序列化，这样就可以自然进行深克隆了
 * @Author poison
 * @Date 2020/10/30 10:08
 */
public class AppTest1 {

    public static void main(String[] args) throws CloneNotSupportedException {
        WeekReport weekReport = new WeekReport();
        weekReport.setEmp("godkey");
        weekReport.setSummary("总结");
        weekReport.setPlan("计划");
        weekReport.setSuggestion("无");
        weekReport.setTime(new Date());


        WeekReport clone = (WeekReport) weekReport.clone();
        clone.setTime(new Date(0));
        System.out.println(weekReport);
        System.out.println(clone);

    }
}

@Data
class WeekReport1 implements Cloneable, Serializable {
    private int id;
    private String emp;
    private String summary;
    private String plan;
    private String suggestion;
    private Date time;

//    @Override
//    protected Object clone() throws CloneNotSupportedException {
//         // 浅拷贝，直接复制目标对象的二进制地址，如果要复制的类中包含对象，比如Date，当复制的类修改时，原有的类也会被修改
//        return super.clone();
//    }

    /**
     * 重写方法，解决浅拷贝问题
     * 这种方法过于麻烦
     * @return
     * @throws CloneNotSupportedException
     */
//    @Override
//    public Object clone() throws CloneNotSupportedException {
//        // 解决浅拷贝问题，将data对象也进行clone，这样新对象的Date就指向了不同地址
//        // 可以将其存入缓存中
//        // 缺点，当嵌套对象过多的时候clone就会很麻烦
//        WeekReport1 weekReport = (WeekReport1) super.clone();
//        Date date = (Date) weekReport.getTime().clone();
//        weekReport.setTime(date);
//        return weekReport;
//    }

    //    @Override
    @SneakyThrows
    protected Object clone() throws CloneNotSupportedException {
        // 因为实现了序列化接口，因此我们直接进行存盘
        // 假设存了盘，然后我们再从盘中将对象读出，然后反序列化
        // 这样就不用手动进行复杂的clone了
        //FileOutputStream outputStream = new FileOutputStream("");
        // 放置到内存中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(this);
        objectOutputStream.close();
        // 从内存中获取字节数组
        byte[] bytes = outputStream.toByteArray();

        //FileInputStream inputStream = new FileInputStream("");
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        Object readObject = objectInputStream.readObject();
        objectInputStream.close();
        return readObject;
    }


}
